package cn.mdmbct.douyin.common.executor;

import cn.mdmbct.douyin.common.bean.AccessToken;
import cn.mdmbct.douyin.common.constant.RequestParameterName;
import cn.mdmbct.douyin.common.enums.ApiPlatform;
import cn.mdmbct.douyin.common.enums.DyOpenApi;
import cn.mdmbct.douyin.common.enums.RequestBodyType;
import cn.mdmbct.douyin.common.exception.ApiCallException;
import cn.mdmbct.douyin.common.exception.InvalidRequestParamException;
import cn.mdmbct.douyin.common.http.Head;
import cn.mdmbct.douyin.common.http.HttpExecutor;
import cn.mdmbct.douyin.common.proxy.ParamCache;
import cn.mdmbct.douyin.common.proxy.annotations.Mapping;
import cn.mdmbct.douyin.common.response.DefaultResponseData;
import cn.mdmbct.douyin.common.session.DySession;

import java.lang.reflect.Method;

/**
 * @author mdmbct  mdmbct@outlook.com
 * @date 5/10/2021 21:53 AM
 * @modified mdmbct
 * @since 1.0
 */
public class ServiceExecutor {


    protected final DySession dySession;

    protected final HttpExecutor httpExecutor;

    protected final ParamCache paramCache;

    protected final DyTokenManager tokenManager;

    public ServiceExecutor(DySession dySession, HttpExecutor httpExecutor) {
        this.dySession = dySession;
        this.httpExecutor = httpExecutor;
        this.paramCache = new ParamCache();
        this.tokenManager = new DefaultTokenManager(dySession);
    }

    /**
     * get请求 自动拼接请求url中的access_token参数
     *
     * @param openId open id 方便自动获取token
     * @param url  拼装完数据的url 但是该url中不能含有{@link RequestParameterName#ACCESS_TOKEN}参数
     * @param apiPlatform 调用的授权api所属平台 {@link ApiPlatform}
     * @param heads 请求头
     * @return 返回的json数据
     * @throws ApiCallException 接口调用异常
     * @throws InvalidRequestParamException 无效的请求参数、url异常
     */
    public String getRequest(String openId, String url, ApiPlatform apiPlatform, Head... heads) throws ApiCallException, InvalidRequestParamException {

        // 获取AccessToken 自动刷新 不会返回null
        AccessToken accessToken = tokenManager.getAccessToken(openId, apiPlatform, true);
        // 拼接上access_token参数
        String competedUrl = completeUrl(url, accessToken.getValue());
        return httpExecutor.executeGet(heads, competedUrl);
    }

    /**
     * post请求 自动拼接请求url中的access_token参数
     *
     * @param <T>  body类型
     * @param url  拼装完数据的url 但是该url中不能含有access_token参数
     * @param body 请求体
     * @param openId open id 方便自动获取token
     * @param apiPlatform 调用的授权api所属平台 {@link ApiPlatform}
     * @param requestBodyType 请求体类型 {@link RequestBodyType}
     * @param heads 请求头
     * @return 返回的json数据
     * @throws ApiCallException 接口调用异常
     * @throws InvalidRequestParamException 无效的请求参数、url异常
     */
    public <T> String postRequest(String url, T body, String openId, ApiPlatform apiPlatform, RequestBodyType requestBodyType, Head... heads) throws ApiCallException, InvalidRequestParamException {

        AccessToken accessToken = tokenManager.getAccessToken(openId, apiPlatform, true);
        String competedUrl = completeUrl(url, accessToken.getValue());
        return httpExecutor.executePost(heads, competedUrl, body, requestBodyType);
    }


    /**
     * 补全参数access_token
     *
     * @param originalUrl 未补全的url
     * @param accessToken access token的值
     * @return 补全之后的url
     */
    private String completeUrl(String originalUrl, String accessToken) {

        StringBuilder urlBuilder = new StringBuilder(originalUrl);
        if (originalUrl.endsWith(RequestParameterName.PARAM_AND)) {
            return urlBuilder.append(RequestParameterName.ACCESS_TOKEN).append("=").append(accessToken).toString();
        } else {
            return urlBuilder.append(RequestParameterName.PARAM_AND).append(RequestParameterName.ACCESS_TOKEN).append("=").append(accessToken).toString();
        }
    }

    /**
     * 依据API格式化url
     *
     * @param mapping      mapping
     * @param platform api所属平台
     * @param params   api参数
     * @return 格式化之后的api 请求url
     */
    public String formatRequestUrl(Mapping mapping, ApiPlatform platform, Object... params) {
        return null;
    }

    /**
     * 由api直接发送无请求头的get请求 并直接返回数据
     *
     * @param api               api
     * @param openId            open id
     * @param platform          api平台
     * @param responseDataClass 响应的data字段类型
     * @param urlParams         请求参数
     * @param <D>               响应的data字段类型
     * @return 响应的data字段实例
     */
    public <D extends DefaultResponseData> D simpleGetReq(DyOpenApi api, String openId, ApiPlatform platform, Class<D> responseDataClass, Object... urlParams) {
        return null;
    }

    public <D extends DefaultResponseData> D executor(Method method, Object[] args) {





        return null;
    }




}
